package lumis.service.content.preview;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import lumis.content.ContentManagerFactory;
import lumis.content.core.ContentPublication;
import lumis.content.core.ContentVersion;
import lumis.doui.DouiContext;
import lumis.doui.DouiManagerFactory;
import lumis.doui.render.RenderDataValue;
import lumis.doui.service.DouiServiceInterfaceInstanceDefinition;
import lumis.doui.service.IDouiDefinitionProcessor;
import lumis.doui.source.IDataProvider;
import lumis.doui.source.ISourceData;
import lumis.doui.source.TabularSource;
import lumis.portal.PortalException;
import lumis.portal.PortalRequestParameters;
import lumis.portal.authentication.SessionConfig;
import lumis.portal.manager.ManagerFactory;
import lumis.portal.manager.ManagerFactoryInternal;
import lumis.portal.page.PageConfig;
import lumis.portal.presentation.perspective.Perspective;
import lumis.portal.propertybag.PropertyBag;
import lumis.portal.serviceinterface.ServiceInterfaceConfig;
import lumis.portal.serviceinterfaceinstance.ServiceInterfaceInstanceConfig;
import lumis.util.ITransaction;
import lumis.util.XmlUtil;

import org.apache.wicket.markup.parser.IMarkupFilter;
import org.w3c.dom.Node;

/**
 * Data provider that returns the pages that the given item id may be seen by the end user.
 * <p>
 * All pages that contain only administration interfaces are ignored
 * <p>
 *
 * @version $Revision: 13161 $ $Date: 2011-06-22 11:33:17 -0300 (Wed, 22 Jun 2011) $
 * @since 4.1.0
 */
public class PreviewPagesDataProvider implements IDataProvider<TabularSource<?>>
{
	private static final String PREVIEW_SKINLIST = "lumis.service.content.preview.skinlist";
	
	public void loadData(SessionConfig sessionConfig, TabularSource<?> source, ITransaction transaction) throws PortalException
	{
		String itemId = (String)source.getParameterValue("itemId");

		if(itemId != null)
		{
			Set<String> serviceInstanceIds = new HashSet<String>();
			Set<String> pageIds = new HashSet<String>();
			String sourceId = null;

			// calculate the service instance Ids based on the published to service instance list.
			ContentVersion contentVersion = ContentManagerFactory.getContentManager().getContentVersionByItemId(itemId);
			for(ContentPublication contentPublication : contentVersion.getPublications())
			{
				serviceInstanceIds.addAll(contentPublication.getServiceInstanceIds());
			}

			// get all the interface instances that do not have parent templates for the given service instance
			for(String serviceInstanceId : serviceInstanceIds)
			{
				Collection<String> interfaceInstanceIds = ManagerFactory.getServiceInterfaceInstanceManager().getIdsByServiceInstanceId(sessionConfig, serviceInstanceId, false, transaction);
				for(String interfaceInstanceId : interfaceInstanceIds)
				{
					ServiceInterfaceInstanceConfig interfaceInstanceConfig = ManagerFactory.getServiceInterfaceInstanceManager().get(sessionConfig, interfaceInstanceId, transaction);
					ServiceInterfaceConfig serviceInterfaceConfig =  ManagerFactory.getServiceInterfaceManager().getServiceInterfaceConfig(interfaceInstanceConfig.getServiceInterfaceId(), transaction);
					if(interfaceInstanceConfig.getParentInterfaceInstanceId() == null && serviceInterfaceConfig.isPreviewSupported())
					{
						String pageId = interfaceInstanceConfig.getPageId();
						if (pageId != null)
						{
							if (!pageIds.contains(pageId))
							{
								if (sourceId != null)
								{
									// make sure the interface contains the itemId's source
									DouiContext douiContext = source.getDouiContext();
									IDouiDefinitionProcessor processor = douiContext != null ? douiContext.getDouiDefinitionProcessor() : null;
									DouiServiceInterfaceInstanceDefinition interfaceDouiDefinition = DouiManagerFactory.getDouiManager().getDouiServiceInterfaceInstanceDefinition(
										sessionConfig, interfaceInstanceConfig.getId(), processor, transaction);
									Node[] sourceNodes = interfaceDouiDefinition.getSourceDefinitionNodes();
									boolean sourceFound = false;
									for (Node sourceNode : sourceNodes)
									{
										if(sourceId.equals(XmlUtil.readAttributeString("id", sourceNode)) || sourceId.equals(XmlUtil.readAttributeString("metaDataSourceId", sourceNode)))
										{
											sourceFound = true;
											break;
										}
									}

									if (!sourceFound)
										continue;
								}

								String pageUrl = PortalRequestParameters.PAGE_PARAMETER_PERSPECTIVE+"="+Perspective.USER.value()+"&"+PortalRequestParameters.PAGE_PARAMETER_TEMPORARY_MODE+"=1&lumPageId="+pageId+"&previewItemId="+itemId+"&lumHighlightII="+interfaceInstanceConfig.getId();
								pageIds.add(pageId);

								ISourceData row = source.getData().addRow();
								PageConfig pageConfig = ManagerFactory.getPageManager().get(sessionConfig, pageId, transaction);
								String parentPath = ManagerFactory.getChannelManager().getPath(sessionConfig, pageConfig.getChannelId(), transaction);
								parentPath = parentPath.substring(1);
								if (parentPath.length() > 100)
									parentPath = "..." + parentPath.substring(parentPath.length() - 100);
								row.put("id", pageUrl);
								row.put("name", pageConfig.getName() + " (" + parentPath + ")");
								
								// calculate the skins
								PropertyBag pagePropertyBag = ManagerFactory.getPropertyBagManager().get(pageConfig.getPropertyBagId());
								String skinList = pagePropertyBag.getValue(PREVIEW_SKINLIST, "lum_default");
								
								List<String> skins = ManagerFactoryInternal.getDeviceSkinManager().getSkinList(skinList);

								if(skins != null)
								{
									StringBuilder skinNames = new StringBuilder();
									for(String skin : skins)
									{
										skinNames.append("<skin>"+XmlUtil.encodeXml(skin)+"</skin>");
									}
									
									row.put("deviceskins", new RenderDataValue(skinNames.toString()));
								}
							}
						}
					}
				}
			}
			source.getData().sort(source);
		}
	}
}
